﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TinyPG
{
    public class Branche
    {
        public List<Branche> _listBrancheNext;
        public List<Branche> _listBranchePrev;
        public List<Branche> _listBrancheRetourAval;
        public List<Branche> _listBrancheRetourAmont;

        public bool _beginEnd;
        public float _a;
        public float _b;
        public float _c;
        public float _d;
        public float _AmLib;
        public float _AvLib;
        public float _Largeur;
        public float _nbCase;

        public float _Xmin;
        public float _Xint;
        public float _Xpos;

        public int _Ymin;
        public int _Ymax;
        public int _Yint;
        public int _Ypos;

        public List<Element> _listElements;
        private int[] _Position;
        private bool _OK;

        public bool _isNoeud;

        public void DeplacerDroite ()
        {
            _Xpos++;
            _Xmin++;
        }

        public void DeplacerGauche()
        {
            _Xpos--;
            _Xmin--;
        }

        public void DeplacerDescend()
        {
            _Ypos++;
            _Ymin++;
        }

        public void DeplacerMonte()
        {
            _Ypos--;
            _Ymin--;
        }

        public Branche(bool IsNoeud)
        {
            _listBrancheRetourAval = new List<Branche>();
            _listBrancheRetourAmont = new List<Branche>();
            _listBrancheNext = new List<Branche>();
            _listBranchePrev = new List<Branche>();
            _listElements = new List<Element>();
            _Position = new int[2];
            _isNoeud = IsNoeud;

            _a = 0;
            _b = 0;
            _c = -1;
            _d = 0;
            _AmLib = 0;
            _AvLib = 0;
            _Largeur = 1;

            _nbCase = 1;

            _Xmin = 0;
            _Xint = 0;
            _Xpos = 0;

            _Ymin = -1;
            _Yint = -1;
            _Ymax = 0;
            _Ypos = -1;

            _beginEnd = false;
        }

        public void ResetValeur()
        {
            _a = 0;
            _b = 0;
            _c = -1;
            _d = 0;
            _AmLib = 0;
            _AvLib = 0;
            _Largeur = 1;

            _Xmin = 0;
            _Xint = 0;
            _Xpos = 0;

            _Ymin = -1;
            _Yint = -1;
            _Ymax = 0;
            _Ypos = -1;
        }

        public bool GetOk()
        {
            return _OK;
        }

        public int[] GetPos()
        {
            return _Position;
        }

        public void SetPos(int x, int y)
        {
            _Position[0] = x;
            _Position[1] = y;
            _OK = true;
        }

        public int GetSize()
        {
            return _listElements.Count;
        }

        public void AddElement(Element E)
        {
            _listElements.Add(E);
        }
        public void AddBrancheNext(Branche B)
        {
            _listBrancheNext.Add(B);
        }
        public void AddBranchePrev(Branche B)
        {
            _listBranchePrev.Add(B);
        }
        public void AddVersBrancheRetour(Branche B)
        {
            _listBrancheRetourAval.Add(B);
        }

        public void SetLargeur()
        {
            foreach (Element E in _listElements)
            {
                if (E.GetType() == typeof(Etape))
                {
                    _nbCase = Math.Max(_nbCase, E._listActions.Count + 1);
                }
            }
        }

        public bool Rechercher(Branche Brecherche, List<Branche> BranchesParcourues)
        {
            if (this == Brecherche || BranchesParcourues.IndexOf(this) > -1)
            {
                if (this == Brecherche)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                BranchesParcourues.Add(this);
                bool trouve = false;
                foreach (Branche B in _listBrancheNext)
                {
                    if (B.Rechercher(Brecherche, BranchesParcourues))
                    {
                        trouve = true;
                        break;
                    }


                }
                return trouve;
            }
        }

        public void Set_Ymin_a()
        {
            foreach (Branche B in _listBrancheNext)
            {
                bool Ok = true;
                int Ymin = -1;
                float valA = 0;
                foreach (Branche Bprev in B._listBranchePrev)
                {
                    if (Bprev._Ymin == -1)
                    {
                        Ok = false;
                        break;
                    }
                    else
                    {
                        if (Bprev._isNoeud)
                        {
                            if (Ymin < Bprev._Ymin)
                            {
                                Ymin = Bprev._Ymin;
                            }
                        }
                        else
                        {
                            if (Ymin < Bprev._Ymin + Bprev._listElements.Count + 1)
                            {
                                Ymin = Bprev._Ymin + Bprev._listElements.Count + 1;
                            }
                        }
                        valA += Bprev._a;

                    }
                }
                if (Ok)
                {
                    B._Ymin = Ymin;
                    if (B._listBranchePrev.Count == 1 && B._listBranchePrev[0]._listBrancheNext.Count > 1)
                    {
                        B._a = B._nbCase;
                    }
                    else
                    {
                        B._a = Math.Max(valA, B._nbCase);
                    }

                    if (B._listBrancheNext.Count > 0)
                    {
                        B.Set_Ymin_a();
                    }

                }

            }
        }

        public void Set_Ymax_b()
        {
            foreach (Branche B in _listBranchePrev)
            {
                bool Ok = true;
                int Ymax = _Ymax;
                float valB = 0;
                float AvLib = 0;
                foreach (Branche Bnext in B._listBrancheNext)
                {
                    if (Bnext._Ymax == 0)
                    {
                        Ok = false;
                        break;
                    }
                    else
                    {
                        if (B._isNoeud)
                        {
                            if (Ymax > Bnext._Ymax)
                            {
                                Ymax = Bnext._Ymax;
                            }
                        }
                        else
                        {
                            if (Ymax > Bnext._Ymax - B._listElements.Count - 1)
                            {
                                Ymax = Bnext._Ymax - B._listElements.Count - 1;
                            }
                        }

                        AvLib += Math.Max(Bnext._a, Bnext._b);
                        valB += Bnext._b;

                    }
                }
                if (Ok)
                {

                    B._Ymax = Ymax;
                    if (B._listBrancheNext.Count == 1 && B._listBrancheNext[0]._listBranchePrev.Count > 1)
                    {
                        B._b = B._nbCase;
                    }
                    else
                    {
                        B._b = Math.Max(valB, B._nbCase);
                    }

                    if (Math.Max(B._a, B._b) > AvLib)
                    {
                        B._AvLib = Math.Max(B._a, B._b) - AvLib;
                    }
                    if (B._listBranchePrev.Count > 0)
                    {
                        B.Set_Ymax_b();
                    }

                }

            }
        }

        public void Set_c()
        {
            foreach (Branche B in _listBrancheNext)
            {
                bool Ok = true;
                float valC = 0;
                float AmLib = 0;
                foreach (Branche Bprev in B._listBranchePrev)
                {
                    if (Bprev._c == -1)
                    {
                        Ok = false;
                        break;
                    }
                    else
                    {
                        valC += Bprev._c;
                        AmLib += Math.Max(Bprev._a, Bprev._b);
                    }
                }
                if (Ok)
                {
                    if (B._listBranchePrev.Count == 1 && B._listBranchePrev[0]._listBrancheNext.Count > 1)
                    {
                        B._c = Math.Max(B._a, B._b) + (B._listBranchePrev[0]._AvLib / B._listBranchePrev[0]._listBrancheNext.Count);
                    }
                    else
                    {
                        B._c = Math.Max(Math.Max(B._a,B._b),valC);
                    }
                    if (B._c > valC)
                    {
                        B._AmLib = B._c - AmLib;
                    }
                    if (B._listBrancheNext.Count > 0)
                    {
                        B.Set_c();
                    }

                }

            }
        }

        public void Set_d()
        {
            foreach (Branche B in _listBranchePrev)
            {
                bool Ok = true;
                float valD = 0;
                foreach (Branche Bprev in B._listBrancheNext)
                {
                    if (Bprev._d == -1)
                    {
                        Ok = false;
                        break;
                    }
                    else
                    {
                        valD += Bprev._d;
                    }
                }
                if (Ok)
                {

                    if (B._listBrancheNext.Count == 1 && B._listBrancheNext[0]._listBranchePrev.Count > 1)
                    {
                        B._d = B._c + B._listBrancheNext[0]._AmLib / B._listBrancheNext[0]._listBranchePrev.Count;
                    }
                    else
                    {
                        B._d = Math.Max(B._c, valD);
                    }
                    B._Largeur = B._d;


                    if (B._listBranchePrev.Count > 0)
                    {
                        B.Set_d();
                    }
                }

            }
        }

        public void Set_Ypos()
        {
            foreach (Branche B in _listBranchePrev)
            {
                if (!B._beginEnd && B._Ypos == -1)
                {
                    if (B._isNoeud)
                    {
                        if (B._Ymax > _Ypos)
                        {
                            B._Ypos = _Ypos;
                        }
                        else
                        {
                            B._Ypos = B._Ymax;
                        }
                    }
                    else
                    {
                        if (B._Ymax > _Ypos - B._listElements.Count - 1)
                        {
                            B._Ypos = _Ypos - B._listElements.Count - 1;
                        }
                        else
                        {
                            B._Ypos = B._Ymax;
                        }
                    }

                    B.Set_Ypos();
                }
            }
            foreach (Branche B in _listBrancheNext)
            {
                int Ypos = B._Ymin;

                if (_isNoeud)
                {
                    if (Ypos < _Ypos)
                    {
                        Ypos = _Ypos;
                    }
                }
                else
                {
                    if (Ypos < _Ypos + _listElements.Count + 1)
                    {
                        Ypos = _Ypos + _listElements.Count + 1;
                    }
                }
                B._Ypos = Ypos;
                if (!B._beginEnd)
                {
                    B.Set_Ypos();
                }



            }
        }

        public void Set_Xmin_Xint()
        {
            float rang = _Xmin;
            foreach (Branche B in _listBrancheNext)
            {
                if (B._Xmin == 0)
                {
                    B._Xmin = rang;

                    if (B._listBranchePrev.Count == 1 && B._listBranchePrev[0]._listBrancheNext.Count == 1)
                    {
                        B._Xint = Math.Min(_Xint, B._Xmin + (B._Largeur - B._nbCase) / 2);
                    }
                    else
                    {
                        B._Xint = B._Xmin + (B._Largeur - B._nbCase) / 2;
                    }

                    rang += B._Largeur;
                    B.Set_Xmin_Xint();

                }

            }
        }

        public void Set_Xpos()
        {
            foreach (Branche B in _listBranchePrev)
            {
                if (B._Xpos == 0)
                {
                    if (B._listBrancheNext.Count == 1 && B._listBrancheNext[0]._listBranchePrev.Count == 1)
                    {
                        B._Xpos = Math.Min(_Xpos, B._Xmin + (B._Largeur - B._nbCase) / 2);
                    }
                    else
                    {
                        B._Xpos = B._Xmin + (B._Largeur - B._nbCase) / 2;
                    }
                    B._Xpos = Math.Min(B._Xpos, B._Xint);
                    B.Set_Xpos();

                }

            }
        }

    }
}
